/*jslint browser: true, devel: true, bitwise: true, white: true, plusplus: true, forin:true, nomen:true */
/*global $:true, define:true */

/**
 * @module Test
 */

define(['WID/Test/Reporter'],function(Reporter) {
"use strict";

/** 
 * 
 * @class HTMLReport
 * @constructor
 */
function HTMLReport(reportData) {
	this.Root = undefined;
	this.GenerateTime = undefined;
	
	this.ReportData =  reportData;
	this.Current = reportData.results;
	
	this.generate();
	
} //var extend = Object.create(); extend.constructor = HTMLReport;
var extend = HTMLReport.prototype;
HTMLReport.CHEADER = 'tHeader';
HTMLReport.CSUMMARY = 'tSummary';
HTMLReport.CSUITE = 'tSuite';
HTMLReport.CTESTCASE = 'tTestCase';
HTMLReport.CTEST = 'tTest';
HTMLReport.CCAPTION = 'tCaption';
HTMLReport.CFAILURE = 'tFailure';
HTMLReport.CFOOTER = 'tFooter';

extend.generate = function() {
	var 
		startTime = Date.now(),
		allTime = this.ReportData.time;
		
	this.Root = this.createElement('div');
	this.Root.setAttribute('id','widHTMLReporter');
	
	this.renderHeader();
	this.renderSummary();
	this.renderFooter();
	
	allTime += (Date.now()-startTime)/1000;
	this.GenerateTime.appendChild(this.createText('Generated report time: '+allTime+' s'));
	$(this.Root).appendTo($(document.body));
};

extend.renderHeader = function() {
	var 
		header = this.createElement('div'),
		totalElement = this.createElement('p'),
		span,
		data = this.ReportData;
		
	header.setAttribute('class',HTMLReport.CHEADER);
	this.GenerateTime = this.createElement('h4');
	header.appendChild(this.GenerateTime);
	
	totalElement.appendChild(this.createText('Total Suites: '+data.totalSuites));
	header.appendChild(totalElement);
	
	totalElement = totalElement.cloneNode(false);
	totalElement.appendChild(this.createText('Total Cases: '+data.totalCases));
	header.appendChild(totalElement);
	
	totalElement = totalElement.cloneNode(false);
	totalElement.appendChild(this.createText('Total Tests: '+data.totalTests));
	header.appendChild(totalElement);
	
	totalElement = totalElement.cloneNode(false);
	totalElement.appendChild(this.createText(' Tests (Passed/Failure): '));
	span = this.createElement('span');
	span.style.color = 'green';
	span.appendChild(this.createText(data.totalTests-data.failures.length));
	totalElement.appendChild(span);
	
	span = span.cloneNode(false);
	span.style.color = '';
	span.appendChild(this.createText(' / '));
	totalElement.appendChild(span);
	
	span = span.cloneNode(false);
	span.style.color = 'red';
	span.appendChild(this.createText(data.failures.length));
	totalElement.appendChild(span);
	header.appendChild(totalElement);
	
	this.Root.appendChild(header);
};

extend.renderSummary = function() {
	var summary = this.createElement('div');
	summary.setAttribute('class',HTMLReport.CSUMMARY);
	this.renderFailures(summary);
	this.render(this.Current,summary);
	
	this.Root.appendChild(summary);
};
extend.renderFooter = function() {
	
};

extend.createElement = function(type) {
	return document.createElement(type);
};

extend.createText = function(text) {
	return document.createTextNode(text);
};

extend.render = function(results,parentNode) {
	var 
		i,
		children = results.children,
		len = children.length,
		childResults;
			
	for (i = 0; i < len;++i) {
		childResults = children[i];
		if (childResults.type === Reporter.SUITE) {
			this.render(childResults,this.renderSuite(childResults,parentNode));
		} else if (childResults.type === Reporter.CASE) {
			this.render(childResults,this.renderTestCase(childResults,parentNode));
		} else {
			this.renderTest(childResults,parentNode);
		}
	}
};

extend.renderFailures = function(parentNode) {
	if (this.ReportData.failures.length) {
		var 
			i, failures = this.ReportData.failures, len = failures.length,
			fdiv = this.createElement('div');
			
		for (i = 0; i < len; ++i) {
			this.renderFailure(failures[i],fdiv);
		}
		
		parentNode.appendChild(fdiv);
	}
};

extend.renderFailure = function(results,parentNode) {
	var 
		failure = this.createElement('div'),
		caption = this.createElement('div'),
	  content = this.createElement('div');
	
	caption.appendChild(this.createText(results.end.fullname));
	caption.setAttribute('class',HTMLReport.CCAPTION+' tFailureCaption');
	
	failure.appendChild(caption);
	failure.setAttribute('class',HTMLReport.CTEST+' '+HTMLReport.CFAILURE);
	failure.appendChild(content);
	
	if (results.end.error) {
		this.renderError(results.end.error,content);
	}
	
	if (results.end.exps) {
		this.renderExps(results.end.exps,content);
	}
	
	caption.onclick = function() {
		if (!content.style.display) {
			content.style.display = 'none';
		} else {
			content.style.display = '';
		}
	};
	
	parentNode.appendChild(failure);
};

extend.renderError = function(errorData,parentNode) {
	var 
	error = this.createElement('div'),
	name = this.createElement('p'),
	stack = this.createElement('div'),
	stackElement = this.createElement('p'),
	i,stackData = errorData.stack,len = stackData.length;
	
	name.appendChild(this.createText(errorData.name));
	error.appendChild(name);
	for (i = 0; i < len; ++i) {
		stackElement.appendChild(this.createText(stackData[i]));
		stack.appendChild(stackElement);
		stackElement = stackElement.cloneNode(false);
	}
	error.appendChild(stack);	
	error.setAttribute('class','tError');
	parentNode.appendChild(error);	
};

extend.renderExps = function(exps,parentNode) {
	var 
		i,
		len=exps.length,
		info;
	for (i = 0; i < len; ++i) {
		info = this.createElement('p');
		info.innerHTML = '<p>'+exps[i]+'</p>';
		parentNode.appendChild(info);	
	}
};

extend.renderSuite = function(results, parentNode) {
	var 
		suite = this.createElement('div'),
		caption = this.createElement('div'),
	  content = this.createElement('div');
	
	caption.appendChild(this.createCaption(results.start.name,results.start.desc,results.time));
	caption.setAttribute('class',HTMLReport.CCAPTION);
	suite.appendChild(caption);
	suite.appendChild(content);
	suite.setAttribute('class',HTMLReport.CSUITE);
	
	if (results.end.failed) {
		caption.setAttribute('class',HTMLReport.CCAPTION+' tFailureCaption');
		suite.setAttribute('class',HTMLReport.CSUITE+' '+HTMLReport.CFAILURE);
	} else {
		content.style.display = 'none';
	}
	
	caption.onclick = function() {
		if (!content.style.display) {
			content.style.display = 'none';
		} else {
			content.style.display = '';
		}
	};
	
	parentNode.appendChild(suite);
	return content;
};

extend.renderTestCase = function(results, parentNode) {
	var 
		testCase = this.createElement('div'),
		caption = this.createElement('div'),
	  content = this.createElement('div');
	
	caption.appendChild(this.createCaption(results.start.name,results.start.desc,results.time));
	caption.setAttribute('class',HTMLReport.CCAPTION);
	testCase.appendChild(caption);
	testCase.appendChild(content);
	testCase.setAttribute('class',HTMLReport.CTESTCASE);
	
	if (results.end.failed) {
		caption.setAttribute('class',HTMLReport.CCAPTION+' tFailureCaption');
		testCase.setAttribute('class',HTMLReport.CTESTCASE+' '+HTMLReport.CFAILURE);
	} else {
		content.style.display = 'none';
	}

	caption.onclick = function() {
		if (!content.style.display) {
			content.style.display = 'none';
		} else {
			content.style.display = '';
		}
	};
	
	parentNode.appendChild(testCase);
	return content;
};

extend.renderTest = function(results, parentNode) {
	var 
		test = this.createElement('div'),
		caption = this.createElement('div'),
	  content;
	
	caption.appendChild(this.createCaption(results.start.name,results.end.desc,results.time));
	caption.setAttribute('class',HTMLReport.CCAPTION);
	test.appendChild(caption);
	test.setAttribute('class',HTMLReport.CTEST);
	 
	if (results.end.failed) {
		caption.setAttribute('class',HTMLReport.CCAPTION+' tFailureCaption');
		test.setAttribute('class',HTMLReport.CTEST+' '+HTMLReport.CFAILURE);
		content = this.createElement('div');
		
		if (results.end.error) {
			this.renderError(results.end.error,content);
		}
	
		if (results.end.exps) {
			this.renderExps(results.end.exps,content);
		}
		
		test.appendChild(content);
		caption.onclick = function() {
		if (!content.style.display) {
			content.style.display = 'none';
		} else {
			content.style.display = '';
		}
	};
	}
	
	parentNode.appendChild(test);
};

extend.renderFooter = function() {
	var 
		footer = this.createElement('div'),
		generatorInfo = this.createElement('h4');
		
	footer.setAttribute('class',HTMLReport.CFOOTER);
	generatorInfo.appendChild(this.createText('Testing with Web in Dream Test Module'));
	footer.appendChild(generatorInfo);
	this.Root.appendChild(footer);
};
extend.createCaption = function(name, desc, time) {
	var text;
	if (desc) {
		text = name+' ('+desc+')';
	} else {
		text = name;
	}
	
	return this.createText(text+((time !== 0)?(' '+time+' s'):''));
};

//HTMLReport.prototype = extend;
return HTMLReport;

});
